package codec;

import entity.RpcRequest;
import entity.RpcResponse;
import enumeration.PackageType;
import enumeration.RpcError;
import exception.RpcException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import serializer.Serializer;

import java.util.List;

/*
 * 自定义解码器 byteBuf -> object
 * 自定义协议格式
 * magicType: 魔数
 * 包类型 pacgetype：请求/响应
 * 数据长度 length：tcp 粘包 半包问题
 * 数据 data: 储存实际数据。
* +---------------+---------------+-----------------+-------------+
|  Magic Number |  Package Type | Serializer Type | Data Length |
|    4 bytes    |    4 bytes    |     4 bytes     |   4 bytes   |
+---------------+---------------+-----------------+-------------+
|                          Data Bytes                           |
|                   Length: ${Data Length}                      |
+---------------------------------------------------------------+
 * */
public class CommonDecoder extends ReplayingDecoder {
    private static final Logger logger = LoggerFactory.getLogger(CommonDecoder.class);
    private int MAGIC_TYPE = 0xCAFEBABE;


    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
        //in -> list bytebuf -> list 集合
        int magic = in.readInt();
        if (magic != MAGIC_TYPE) {
            logger.error("未知的协议包");
            throw new RpcException(RpcError.UNKNOWN_PROTOCOL);
        }
        //包类型匹配 请求？响应
        int package_code = in.readInt();
        Class clazz;
        if (package_code == PackageType.REQUEST_PACK.getCode()) {
            clazz = RpcRequest.class;
        } else if (package_code == PackageType.RESPONSE_PACK.getCode()) {
            clazz = RpcResponse.class;
        } else {
            logger.error("不识别的数据包");
            throw new RpcException(RpcError.UNKNOWN_PACKAGE_TYPE);
        }
        //序列化类型
        int serializer_code = in.readInt();
        Serializer serializer = Serializer.getBycode(serializer_code);
        if (serializer == null) {
            logger.error("不识别的序列化格式");
            throw new RpcException(RpcError.UNKNOWN_SERIALIZER);
        }
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
//
        Object deserialize = serializer.deserialize(bytes, clazz);
        //将数据放入集合中 未放入集合 中不会触发事件
        list.add(deserialize);
        logger.info("解码的结果为：{}", deserialize);
    }
}
